module Main where

import System.Environment (getArgs, getEnv)
import System.FilePath ((</>))
import System.IO.Error
import System.IO 
import Control.OldException
import Util
import Helper
import Requests
import Services
import Monad

main :: IO ()

main = handle mainExcHandler $ do
  args <- getArgs
  case args of
    ["contexts"] -> do
        api_key <- getApiKey
        showContexts api_key
    ["add", name] -> do
        api_key <- getApiKey
        addAction api_key "Inbox" "Computer" name
        showNextActions api_key
    [context, "add", name] -> do
        api_key <- getApiKey
        addAction api_key "Inbox" context name
        showNextActionsFiltered (contextsFilter [context]) api_key
    ["--help"] -> do
        putStr . unlines $ 
               "nzb -- command line interface to nozbe.com." :
               "nzb [<context>...] [(add <text> | check <num>)]" :
               "" :
               "nzb  prints next actions, each with a number" :
               "nzb context...  prints next actions from contexts" :
               "nzb check 3  marks action 3 as done" :
               "nzb add 'sth to do'  creates an action" :
               "nzb Home add 'text'  adds next action to Home context" :
               "nzb Home check 2  marks action 2 in Home context as done" :
               "nzb contexts  prints all existing contexts" :
               []

    -- [{context}] [check {number}] where {a} is repeat one or more times
    args -> do
        let (contexts, rest) = break (=="check") args
        case rest of
            "check": rawnums -> do
                api_key <- getApiKey
                Just rsp <- requestNextActions api_key
                let nums = map read rawnums
                let actions = filter (contextsFilter contexts) . filter notDone . parseActions $ rsp
                if any (\num -> num > length actions || num < 1) nums
                    then putStrLn "invalid action number"
                    else do
                        let actionsToCheck = map snd . filter ((`elem`nums).fst) . zip [1..] $ actions
                        checkActions api_key (map actionID actionsToCheck)
                        showNextActionsFiltered (contextsFilter contexts) api_key
            [] -> do
                api_key <- getApiKey
                showNextActionsFiltered (contextsFilter contexts) api_key
            _ -> putStrLn ("invalid arguments")


getApiKey :: IO String
getApiKey = do 
    config_path <- getConfigPath
    config_file_contents <- handle (const $ obtainApiKey config_path) (readFile config_path)
    return (head . words $ config_file_contents)


getConfigPath :: IO String
getConfigPath =
    liftM (</> ".nzb") . handle (const . raise $ noHomeErrMsg) $ getEnv "HOME"
  where
    noHomeErrMsg = "No $HOME environmental variable set.\nTry nzb --help"


obtainApiKey :: String -> IO String
obtainApiKey configPath = do
    hSetBuffering stdout NoBuffering
    putStr "nozbe.com email address: " 
    email <- getLine
    getKey email
  where
    getKey email = do
        putStr "password: "
        hSetEcho stdin False
        password <- getLine
        hSetEcho stdin True
        response <- getApiKeyFromNozbe email password 
        case response of
            Just apiKey -> do
                writeFile configPath apiKey
                return apiKey
            Nothing -> do
                putStrLn "failed to login to nozbe.com"
                getKey email


mainExcHandler :: Exception -> IO ()
mainExcHandler exc = case exc of
        IOException e | isDoesNotExistError e -> do
            let Just filePath = ioeGetFileName e
            putStrLn $ filePath ++ " does not exist\nTry nzb --help"
        e -> putStrLn $ show e
